﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace Btstack
{
    public partial class Bluetooth
    {
        public enum HciRole
        {
            Master,
            Slave
        }

        public enum HciPowerMode
        {
            Off,
            On,
            Sleep
        }

        public enum HciState
        {
            Off,
            Initializing,
            Working,
            Halting,
            Sleeping,
            Falling_asleep
        }

        public enum HciDumpFormat
        {
            Bluez,
            Packetlogger,
            Stdout
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct BtstackLinkedItemType
        {
            private readonly IntPtr next;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct BtstackPacketCallbackRegistrationType
        {
            private readonly BtstackLinkedItemType item;
            public BtstackPacketHandlerType callback;
        }

        public const int HCI_DUMP_LOG_LEVEL_DEBUG = 0;
        public const int HCI_DUMP_LOG_LEVEL_INFO = 1;
        public const int HCI_DUMP_LOG_LEVEL_ERROR = 2;

        [DllImport("btstack-c.dll", EntryPoint = "hci_power_control")]
        private static extern int HciPowerControl(HciPowerMode mode);

        [DllImport("btstack-c.dll", EntryPoint = "hci_close")]
        private static extern int HciClose();

        [DllImport("btstack-c.dll", EntryPoint = "hci_get_state")]
        private static extern HciState HciGetState();

        [DllImport("btstack-c.dll", EntryPoint = "hci_transport_usb_instance")]
        private static extern IntPtr HciTransportUsbInstance();

        [DllImport("btstack-c.dll", EntryPoint = "hci_init")]
        private static extern void HciInit(IntPtr transport, IntPtr config);

        [DllImport("btstack-c.dll", EntryPoint = "hci_add_event_handler")]
        private static extern void HciAddEventHandler(IntPtr CallbackHandler);

        [DllImport("btstack-c.dll", EntryPoint = "hci_dump_open")]
        private static extern void HciDumpOpen(string filename, HciDumpFormat format);

        [DllImport("btstack-c.dll", EntryPoint = "hci_dump_enable_log_level")]
        private static extern void HciDumpEnableLogLevel(int log_level, bool enable);

        [DllImport("btstack-c.dll", EntryPoint = "hci_le_set_own_address_type")]
        private static extern void HciLeSetOwnAddressType(BdAddrType type);

        [DllImport("btstack-c.dll", EntryPoint = "hci_disconnect_all")]
        private static extern void HciDisconnectAll();

        private static byte HciEventPacketGetType(byte[] packet)
        {
            return packet[0];
        }

        private static byte HciEventLeMetaGetSubeventCode(byte[] packet)
        {
            return packet[2];
        }

        private static byte HciSubeventLeConnectionCompleteGetStatus(byte[] packet)
        {
            return packet[3];
        }

        private static HciRole HciSubeventLeConnectionCompleteGetRole(byte[] packet)
        {
            return (HciRole)packet[6];
        }

        private static ushort HciSubeventLeConnectionCompleteGetConnectionHandle(byte[] packet)
        {
            return BitConverter.ToUInt16(packet, 4);
        }

        private static float HciSubeventLeConnectionCompleteGetConnInterval(byte[] packet)
        {
            ushort interval = BitConverter.ToUInt16(packet, 14);
            int fraction = 25 * (interval & 3);
            float integer = interval * 125 / 100;

            if (fraction < 10)
                return integer + fraction / 10f;
            else
                return integer + fraction / 100f;
        }

        private static ushort HciSubeventLeConnectionCompleteGetConnLatency(byte[] packet)
        {
            return BitConverter.ToUInt16(packet, 16);
        }

        private static byte HciEventDisconnectionCompleteGetReason(byte[] packet)
        {
            return packet[5];
        }

        private static byte HciEventDisconnectionCompleteGetStatus(byte[] packet)
        {
            return packet[2];
        }

        private static ushort HciEventDisconnectionCompleteGetConnectionHandle(byte[] packet)
        {
            return BitConverter.ToUInt16(packet, 3);
        }
    }
}
